package com.base.cn.platform.os.common.mybatis.sharding;

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 处理WhereSql
 *
 * @author s.li
 * @create 2019-05-23 11:30
 */
public class WhereSql {

    /**
     * 处理SQL条件
     * @param sqlExpr
     * @param tableNameList
     */
    public static void whereHandle(SQLExpr sqlExpr, List<SQLExprTableSource> tableNameList, Set<String> columnSet, Map<String,Object> shardingValues){
        List<SQLExpr> parameterList = new ArrayList<>();
        if(sqlExpr instanceof SQLMethodInvokeExpr){
            SQLMethodInvokeExpr sqlMethodInvokeExpr = (SQLMethodInvokeExpr)sqlExpr;
            //查询条件列表
            List<SQLExpr> sqlExprList = sqlMethodInvokeExpr.getParameters();
            if(sqlExprList !=null && sqlExprList.size() > 0){
                parameterList.addAll(sqlExprList);
            }
        }else if(sqlExpr instanceof SQLBinaryOpExpr){
            sqlBinaryOpExprHandle((SQLBinaryOpExpr)sqlExpr,parameterList,columnSet,shardingValues);
        }else if(sqlExpr instanceof SQLInSubQueryExpr){
            SQLInSubQueryExpr sqlInSubQueryExpr =(SQLInSubQueryExpr)sqlExpr;
            SelectSql.select(sqlInSubQueryExpr.getSubQuery(),tableNameList,columnSet,shardingValues);
        }
        if(!parameterList.isEmpty()){
            whereParamsHandle(parameterList,tableNameList,columnSet,shardingValues);
        }
    }

    /**
     * 处理where语句中SQLBinaryOpExpr类型的SQL
     * @param opExpr
     * @param parameterList
     */
    public static void sqlBinaryOpExprHandle(SQLBinaryOpExpr opExpr,List<SQLExpr> parameterList, Set<String> columnSet, Map<String,Object> shardingValues){
        SQLExpr left = opExpr.getLeft();
        if(left !=null && left instanceof SQLMethodInvokeExpr){
            SQLMethodInvokeExpr leftExpr = (SQLMethodInvokeExpr)left;
            if(leftExpr.getParameters() !=null && !parameterList.isEmpty()){
                parameterList.addAll(leftExpr.getParameters());
            }
        }else if(left instanceof SQLBinaryOpExpr){
            sqlBinaryOpExprHandle((SQLBinaryOpExpr)left,parameterList,columnSet,shardingValues);
        }else if(left instanceof SQLInSubQueryExpr){
            parameterList.add(left);
        }else if(left instanceof SQLPropertyExpr || left instanceof SQLIdentifierExpr){
            ShardingValueUtil.addShardingValue(columnSet,shardingValues,opExpr);
        }
        SQLExpr right = opExpr.getRight();
        if(right !=null && right instanceof SQLMethodInvokeExpr){
            SQLMethodInvokeExpr rightExpr = (SQLMethodInvokeExpr)right;
            if(rightExpr.getParameters() !=null && !rightExpr.getParameters().isEmpty()){
                parameterList.addAll(rightExpr.getParameters());
            }
        }else if(right instanceof SQLBinaryOpExpr){
            sqlBinaryOpExprHandle((SQLBinaryOpExpr)right,parameterList,columnSet,shardingValues);
        }else if(right instanceof SQLInSubQueryExpr){
            parameterList.add(right);
        }
    }

    /**
     * 处理条件后面的参数
     * @param parameterList SQL条件参数列表
     * @param tableNameList 表名列表
     */
    private static void whereParamsHandle(List<SQLExpr> parameterList,List<SQLExprTableSource> tableNameList, Set<String> columnSet, Map<String,Object> shardingValues){
        for(SQLExpr expr : parameterList){
            if(expr instanceof SQLQueryExpr){
                SQLQueryExpr queryExpr = (SQLQueryExpr) expr;
                SelectSql.select(queryExpr.getSubQuery(),tableNameList,columnSet,shardingValues);
            }else if(expr instanceof SQLInSubQueryExpr){
                SQLInSubQueryExpr queryExpr =(SQLInSubQueryExpr)expr;
                SelectSql.select(queryExpr.getSubQuery(),tableNameList,columnSet,shardingValues);
            }
        }
    }
}
